package com.ssy.lingxi.product.serviceImpl.platform;

import com.ssy.lingxi.common.constant.tree.Node;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.vo.PageVO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.product.entity.customer.CustomerAttributeValue;
import com.ssy.lingxi.product.entity.platform.Attribute;
import com.ssy.lingxi.product.entity.platform.AttributeGroup;
import com.ssy.lingxi.product.entity.platform.AttributeValue;
import com.ssy.lingxi.product.repository.customer.CustomerAttributeValueRepository;
import com.ssy.lingxi.product.repository.platform.AttributeGroupRepository;
import com.ssy.lingxi.product.repository.platform.AttributeRepository;
import com.ssy.lingxi.product.repository.platform.AttributeValueRepository;
import com.ssy.lingxi.product.service.platform.IAttributeValueService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 属性值实现类
 * @author jw.chen
 * @version 2.0.0
 * @date 2020/6/23
 */
@Service
public class AttributeValueServiceImpl implements IAttributeValueService {

    @Autowired
    private AttributeRepository attributeRepository;

    @Autowired
    private AttributeGroupRepository attributeGroupRepository;

    @Autowired
    private AttributeValueRepository attributeValueRepository;

    @Autowired
    private CustomerAttributeValueRepository customerAttributeValueRepository;

    /**
     * 查询属性值树
     * @return Wrapper<List<Node>>
     */
    @Override
    public List<Node> getAttributeValueTree() {
        //一次性查出所有数据
        List<Attribute> attributeList = attributeRepository.findByIsEnable(true);
        List<AttributeGroup> attributeGroupList = attributeGroupRepository.findAll();
        List<AttributeValue> attributeValueList = attributeValueRepository.findAll();

        List<Node> nodeList = new ArrayList<>();
        attributeGroupList.forEach(attributeGroup -> {
            Long attributeGroupId = attributeGroup.getId();
            Node node = new Node();
            node.setId("g_" + attributeGroupId);
            node.setTitle(attributeGroup.getName());
            List<Node> childrenNodeList = attributeTreeChildren(attributeList, attributeValueList, attributeGroupId);
            if(!childrenNodeList.isEmpty()){
                node.setChildren(childrenNodeList);
                nodeList.add(node);
            }
        });
        return nodeList;
    }
    /**
     * 生成子树
     * @param attributeList
     * @param attributeGroupId
     * @return
     */
    private List<Node> attributeTreeChildren(List<Attribute> attributeList, List<AttributeValue> attributeValueList, Long attributeGroupId) {
        List<Node> nodeList = new ArrayList<>();
        attributeList.forEach(attribute -> {
            Long parentId = attribute.getGroupId();
            if(attributeGroupId.longValue() == parentId.longValue()){
                Long attributeId = attribute.getId();
                Node node = new Node();
                node.setId("a_" + attributeId);
                node.setTitle(attribute.getName());
                List<Node> childrenNodeList = attributeValueTreeChildren(attributeValueList, attributeId);
                if(!childrenNodeList.isEmpty()){
                    node.setChildren(childrenNodeList);
                    nodeList.add(node);
                }
            }
        });
        return nodeList;
    }

    /**
     * 生成子树
     * @param attributeValueList
     * @param attributeId
     * @return
     */
    private List<Node> attributeValueTreeChildren(List<AttributeValue> attributeValueList, Long attributeId) {
        List<Node> nodeList = new ArrayList<>();
        attributeValueList.forEach(attributeValue -> {
            Long parentId = attributeValue.getAttribute().getId();
            if(attributeId.longValue() == parentId.longValue()){
                Node node = new Node();
                node.setId("av_" + attributeValue.getId());
                node.setTitle(attributeValue.getValue());
                nodeList.add(node);
            }
        });
        return nodeList;
    }

    /**
     * 查询属性值
     * @param pageVO
     * @param isEnable
     * @param attributeId
     * @param value
     * @return Page<Attribute>
     */
    @Override
    public Page<AttributeValue> getAttributeValueList(PageVO pageVO, Boolean isEnable, Long attributeId, String value){
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        List<Boolean> enaList = isEnable == null ? Stream.of(true, false).collect(Collectors.toList()) : Stream.of(isEnable).collect(Collectors.toList());
        return attributeValueRepository.findByValueContainingAndIsEnableInAndAttributeIdOrderByIdDesc(value, enaList, attributeId, page);
    }

    /**
     * 查询同步属性值列表
     * @param attributeGroupName 属性组名称
     * @param attributeName 属性名称
     * @param attributeValue 属性值
     * @param pageVO 分页实体
     * @return
     */
    @Override
    public Page<AttributeValue> getSyncAttributeValueList(PageVO pageVO, String attributeGroupName, String attributeName, String attributeValue) {
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize());
        return attributeValueRepository.findAll(getSpecification(attributeGroupName, attributeName, attributeValue, true), page);
    }

    /**
     * 查询属性值
     * @return id
     */
    @Override
    public AttributeValue getAttributeValue(Long id){
        return attributeValueRepository.findById(id).orElse(null);
    }

    /**
     * 添加/修改属性值
     * @param attributeValue
     * @return
     * @throws Exception
     */
    @Override
    public String saveOrUpdateAttributeValue(AttributeValue attributeValue){
        Long id = attributeValue.getId();
        String value = attributeValue.getValue();
        List<AttributeValue> attributeValueList;
        //判断平台属性是否存在并且启用
        Attribute attribute = attributeRepository.findById(attributeValue.getAttribute().getId()).orElse(null);
        if(attribute != null){
            Boolean isEnable = attribute.getIsEnable();
            if(!isEnable){
                throw new BusinessException(ResponseCode.PRODUCT_ATTRIBUTE_NOT_ENABLE);
            }
        }else{
            throw new BusinessException(ResponseCode.PRODUCT_ATTRIBUTE_NOT_EXIST);
        }
        Long attributeId = attribute.getId();
        //判断属性值名称是否重复
        if(id != null && id > 0){
            attributeValueList = attributeValueRepository.findByAttributeIdAndValueAndIdNot(attributeId, value, id);
        }else{
            attributeValueList = attributeValueRepository.findByAttributeIdAndValue(attributeId, value);
        }
        if(!attributeValueList.isEmpty()){
            throw new BusinessException(ResponseCode.PRODUCT_ATTRIBUTE_VALUE_NAME_EXIST);
        }

        attributeValueList.add(attributeValue);
        attribute.setAttributeValueList(attributeValueList);
        //数据库持久化对象
        attributeRepository.saveAndFlush(attribute);
        return ResponseCode.SUCCESS.getMessage();
    }

    /**
     * 删除属性值
     * @param id
     * @return
     */
    @Override
    public String deleteAttributeValue(Long id) {
        AttributeValue attributeValue = attributeValueRepository.findById(id).orElse(null);
        if(attributeValue != null){
            Boolean isEnable = attributeValue.getIsEnable();
            if(!isEnable){
                attributeValueRepository.deleteById(id);
                return ResponseCode.SUCCESS.getMessage();
            }else{
                throw new BusinessException(ResponseCode.PRODUCT_ENABLE_NOT_DELETE);
            }
        }
        throw new BusinessException(ResponseCode.PRODUCT_ATTRIBUTE_VALUE_NOT_EXIST);
    }

    /**
     * 启用/停用属性值
     * @param id
     * @param status
     * @return
     */
    @Override
    public String updateAttributeValueStatus(Long id, Boolean status){
        //验证数据库中是否存在该数据
        AttributeValue attributeValue = attributeValueRepository.findById(id).orElse(null);
        if(attributeValue != null){
            if(!status){
                //判断会员属性值是否有关联
                List<CustomerAttributeValue> customerAttributeValueList = customerAttributeValueRepository.findByAttributeValueId(id);
                if(!customerAttributeValueList.isEmpty()){
                    throw new BusinessException(ResponseCode.PRODUCT_CUSTOMER_ATTRIBUTE_VALUE_NOT_STOP);
                }
            }
            //持久化数据
            attributeValue.setIsEnable(status);
            attributeValueRepository.saveAndFlush(attributeValue);
            return ResponseCode.SUCCESS.getMessage();
        }
        throw new BusinessException(ResponseCode.PRODUCT_ATTRIBUTE_VALUE_NOT_EXIST);
    }

    /**
     * 构建查询条件
     * @return
     */
    private Specification<AttributeValue> getSpecification(String attributeGroupName, String attributeName, String attributeValue, Boolean isEnable){
        return (Specification<AttributeValue>) (root, query, criteriaBuilder) -> {
            Predicate finalConditions = criteriaBuilder.conjunction();

            //属性组名称
            if(!StringUtils.isEmpty(attributeGroupName)){
                Predicate predicate = criteriaBuilder.or(criteriaBuilder.like(root.get("attribute").get("groupName").as(String.class), "%" + attributeGroupName + "%"));
                finalConditions = criteriaBuilder.and(finalConditions, predicate);
            }

            //属性名称
            if(!StringUtils.isEmpty(attributeName)){
                Predicate predicate = criteriaBuilder.like(root.get("attribute").get("name").as(String.class), "%" + attributeName + "%");
                finalConditions = criteriaBuilder.and(finalConditions, predicate);
            }

            //属性组名称
            if(!StringUtils.isEmpty(attributeValue)){
                Predicate predicate = criteriaBuilder.like(root.get("value").as(String.class), "%" + attributeValue + "%");
                finalConditions = criteriaBuilder.and(finalConditions, predicate);
            }

            //状态
            if(isEnable != null){
                finalConditions = criteriaBuilder.and(finalConditions, criteriaBuilder.equal(root.get("isEnable"), isEnable));
            }

            //排序
            Order idOrder = criteriaBuilder.desc(root.get("id"));

            return  query.orderBy(idOrder).where(finalConditions).getRestriction();
        };
    }
}

